package com.ybear.ybutils.utils;

import android.animation.ValueAnimator;
import android.content.Context;
import android.view.View;
import android.view.animation.Animation;
import android.view.animation.AnimationUtils;

import androidx.annotation.AnimRes;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.core.util.Consumer;

/**
 * 组件动画工具类
 *
 * @see #loadAnim
 * @see #loadAnim(Context, int, View)
 */
public class AnimUtil {
    public enum SHOW_STATUS {
        NONE,                   //无状态
        AUTO,                   //自动。隐藏方式：GONE
        AUTO_TO_INVISIBLE,      //自动。隐藏方式：INVISIBLE
        VISIBLE,                //显示
        GONE,                   //隐藏模式
        INVISIBLE               //隐藏模式
    }

    /**
     * 加载动画
     * @param mContext  上下文
     * @param animRes   动画资源
     * @param v         需要动画的View
     * @param status    显示状态{@link SHOW_STATUS}
     * @param <V>       泛型继承{@link View}
     * @return          返回动画
     */
    public static <V extends View> Animation loadAnim(Context mContext, @AnimRes int animRes, V v,
                                                      @NonNull SHOW_STATUS status) {
        Animation anim = AnimationUtils.loadAnimation(mContext, animRes);
        //设置动画监听器
        anim.setAnimationListener(new Animation.AnimationListener() {
            @Override
            public void onAnimationStart(Animation animation) { }
            @Override
            public void onAnimationEnd(Animation animation) {
                int show = View.VISIBLE;
                switch ( status ) {
                    case NONE:
                        return;
                    case AUTO:case GONE:
                        show = View.GONE;
                        break;
                    case AUTO_TO_INVISIBLE:case INVISIBLE:
                        show = View.INVISIBLE;
                        break;
                }
                //动画结束时自动隐藏/显示View
                if( SHOW_STATUS.AUTO.equals(status) || SHOW_STATUS.AUTO_TO_INVISIBLE.equals(status) ) {
                    show = v.getVisibility() == View.VISIBLE ? show : View.VISIBLE;
                }
                if( v.getVisibility() != show ) v.setVisibility( show );
            }
            @Override
            public void onAnimationRepeat(Animation animation) { }
        });
        //设置动画
        v.startAnimation( anim );
        return anim;
    }

    public static <V extends View> Animation loadAnim(Context mContext, @AnimRes int animRes, V v) {
        return loadAnim(mContext, animRes, v, SHOW_STATUS.NONE);
    }

    /**
     * 从底部到顶部的动画
     * @param mContext  上下文
     * @param v         需要动画的View
     * @param status    显示状态{@link SHOW_STATUS}
     * @param <V>       泛型继承{@link View}
     */
    public static <V extends View> Animation loadAnimForToTop(Context mContext, V v,
                                                              SHOW_STATUS status) {
        return loadAnim(mContext, R.anim.anim_bottom_in, v, status);
    }
    public static <V extends View> void loadAnimForToTop(Context mContext, V v) {
        loadAnimForToTop(mContext, v, SHOW_STATUS.NONE);
    }

    /**
     * 从顶部到底部的动画
     * @param mContext  上下文
     * @param v         需要动画的View
     * @param status    显示状态{@link SHOW_STATUS}
     * @param <V>       泛型继承{@link View}
     */
    public static <V extends View> Animation loadAnimForToBottom(Context mContext, V v,
                                                                 SHOW_STATUS status) {
        return loadAnim(mContext, R.anim.anim_top_in, v, status);
    }
    public static <V extends View> Animation loadAnimForToBottom(Context mContext, V v) {
        return loadAnimForToBottom(mContext, v, SHOW_STATUS.NONE);
    }

    /**
     * 透明度动画
     * @param alpha         目标透明度值
     * @param duration      时长
     * @param call          动画结束时回调
     * @param vs             View。View显示时：隐藏；隐藏时：显示
     */
    public static void setAlphaAnimator(float alpha, long duration,
                                        @Nullable Consumer<ValueAnimator> call,
                                        @NonNull View... vs) {
        if( vs.length == 0 ) return;
        ValueAnimator anim = ValueAnimator.ofFloat( vs[ 0 ].getAlpha(), alpha );
        anim.setDuration(duration);
        anim.addUpdateListener(animation -> {
            float val = (float) animation.getAnimatedValue();
            for( View v : vs ) v.setAlpha( val );

            if ( alpha >= val && call != null ) {
                call.accept(animation);
            }
        });
        for( View v : vs ) v.setVisibility( View.VISIBLE );
        anim.start();
//        boolean isShow = v.getVisibility() == View.VISIBLE;
//        AlphaAnimation anim = new AlphaAnimation( isShow ? 1F : 0F, alpha );
//        anim.setDuration( duration );
//        anim.setAnimationListener(new Animation.AnimationListener() {
//            @Override
//            public void onAnimationStart(Animation animation) { }
//            @Override
//            public void onAnimationEnd(Animation animation) {
//                if( isShow ) {
//                    if( alpha == 0F ) v.setVisibility( View.GONE );
//                }else {
//                    v.setVisibility( View.VISIBLE );
//                }
////                v.setVisibility( isShow ? View.GONE : View.VISIBLE );
//                if( call != null ) call.accept( animation );
//            }
//            @Override
//            public void onAnimationRepeat(Animation animation) { }
//        });
//        v.clearAnimation();
//        v.setVisibility( View.VISIBLE );
//        v.startAnimation( anim );
    }

    /**
     * 透明度动画
     * @param duration      时长
     * @param call          动画结束时回调
     * @param vs            View。View显示时：隐藏；隐藏时：显示
     */
    public static void setAlphaAnimator(long duration,
                                        @Nullable Consumer<ValueAnimator> call,
                                        @NonNull View... vs) {
        if( vs.length == 0 ) return;
        float alpha = vs[ 0 ].getVisibility() == View.VISIBLE ? 0F : 1F;
        for( View v : vs ) v.setAlpha( alpha == 0F ? 1F : 0F );
        setAlphaAnimator( alpha, duration, call, vs );
    }

    /**
     * 透明度动画
     * @param alpha         目标透明度值
     * @param duration      时长
     * @param vs            View。View显示时：隐藏；隐藏时：显示
     */
    public static void setAlphaAnimator(float alpha, long duration, @NonNull View... vs) {
        setAlphaAnimator( alpha, duration, null, vs );
    }

    /**
     * 透明度动画
     * @param duration      时长
     * @param vs            View。View显示时：隐藏；隐藏时：显示
     */
    public static void setAlphaAnimator(long duration, @NonNull View... vs) {
        setAlphaAnimator( duration, null, vs );
    }
}